package com.duoqin.syncassistant.ui;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.app.AlertDialog;
import android.arch.lifecycle.Observer;
import android.arch.lifecycle.ViewModelProviders;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.content.LocalBroadcastManager;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import com.duoqin.account.DuoqinAccount;
import com.duoqin.account.viewmodel.LoginViewModel;
import com.duoqin.common.ui.AbsActivity;
import com.duoqin.guard.Guard;
import com.duoqin.guard.VerifyGuardCodeHelper;
import com.duoqin.syncassistant.R;
import com.duoqin.syncassistant.SyncAssistantApplication;
import com.duoqin.syncassistant.data.BackupFileRestoreResponse;
import com.duoqin.syncassistant.data.BackupFileInfo;
import com.duoqin.syncassistant.viewmodel.BaseViewModel;
import com.duoqin.syncassistant.viewmodel.SMSSyncViewModel;
import com.duoqin.syncassistant.viewmodel.VCardSyncViewModel;

import java.util.ArrayList;
import java.util.List;

public class SyncAssistantActivity extends AbsActivity {

    private final int REQUEST_LOGIN = 0;
    private final int REQUEST_SYNC_CONTACTS = 1;
    private final int REQUEST_SYNC_SMS = 2;
    private final int REQUEST_VERIFY_GUARD_CODE = 4;

    private VCardSyncViewModel mVCardViewModel;
    private SMSSyncViewModel mSMSViewModel;

    private boolean mQueryVCardInfoSuccess = false;
    private boolean mQuerySMSInfoSuccess = false;
    private boolean mRetryVCardQuery = false;
    private boolean mRetrySMSQuery = false;
    private int mServerSMSCount = 0;
    private long mSmsBackupTime = 0;
    private AlertDialog mAlertDialog;
    private TextView mAccountTV, mContactsCountTV, mContactsBackUpTimeTV, mSMSCountTV, mSmsBackUpTimeTV,mLogOut;
    private View mContactsBackUpView, mSmsBackupView, mProgressView;

    protected BroadcastReceiver mBroadcastReceiver;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_syncassistant);
        setupTitle(getString(R.string.sync_assistant));

        mProgressView = findViewById(R.id.sync_progress);
        mAccountTV = findViewById(R.id.account_id);
        mAccountTV.setOnClickListener(this);
        mLogOut = findViewById(R.id.duoqin_logout_btn);
        mContactsCountTV = findViewById(R.id.records_count);
        mContactsCountTV.setText(getString(R.string.item_count_on_server,
                SyncAssistantApplication.getsInstance().mVCardInfo.getCount()));
        mContactsBackUpTimeTV = findViewById(R.id.contacts_backup_timestamp);
        mSMSCountTV = findViewById(R.id.sms_count);
        mSMSCountTV.setText(getString(R.string.item_count_on_server,
                SyncAssistantApplication.getsInstance().mSMSInfo.getCount()));
        mSmsBackUpTimeTV = findViewById(R.id.sms_backup_timestamp);

        mLogOut.setOnClickListener(this);
        mContactsBackUpView = findViewById(R.id.contacts_backup);
        mContactsBackUpView.setOnClickListener(this);
        mSmsBackupView = findViewById(R.id.sms_backup);
        mSmsBackupView.setOnClickListener(this);
        mSmsBackupTime = System.currentTimeMillis();
        setupBackupTimeStamp();

        setupModelObserver();

        if (SyncAssistantApplication.getsInstance().hasLogin()) {

            mAccountTV.setText(DuoqinAccount.getAccountName(getApplicationContext()));
            if (SyncAssistantApplication.getsInstance().mVCardInfo.getPath() == null) {
                queryServerVCardInfo();
            } else {
                mQueryVCardInfoSuccess = true;
            }
            if (SyncAssistantApplication.getsInstance().mSMSInfo.getPath() == null) {
                queryServerSMSInfo();
            } else {
                mQuerySMSInfoSuccess = true;
            }
        }

        mBroadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                if (SyncAssistantApplication.INTENT_ACTION_TOKEN_EXPIRED.equals(action)) {
                    if (!SyncAssistantApplication.getsInstance().hasLogin()) {
                        mAccountTV.setText(R.string.account_not_login);
                        mContactsCountTV.setText(getString(R.string.item_count_on_server,
                                SyncAssistantApplication.getsInstance().mVCardInfo.getCount()));
                        mSMSCountTV.setText(getString(R.string.item_count_on_server,
                                SyncAssistantApplication.getsInstance().mSMSInfo.getCount()));
                        setupBackupTimeStamp();
                    }
                }
            }
        };
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(SyncAssistantApplication.INTENT_ACTION_TOKEN_EXPIRED);
        LocalBroadcastManager.getInstance(this).registerReceiver(mBroadcastReceiver, intentFilter);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mLogOut.setText(SyncAssistantApplication.getsInstance().hasLogin()?getString(R.string.duoqin_log_out):getString(R.string.duoqin_register_login));
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (mAlertDialog != null && mAlertDialog.isShowing()) {
            mAlertDialog.dismiss();
        }
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        mQueryVCardInfoSuccess = false;
        mQuerySMSInfoSuccess = false;
    }

    private void queryServerVCardInfo() {
        showProgress(true);
        // get vCard info from server
        mQueryVCardInfoSuccess = false;
        mVCardViewModel.getVcardRestoreInfo(
                DuoqinAccount.getAccountToken(getApplicationContext()), 0, 0);
    }

    private void queryServerSMSInfo() {
        showProgress(true);
        mQuerySMSInfoSuccess = false;
        mSMSViewModel.getSMSRestoreInfo(
                DuoqinAccount.getAccountToken(getApplicationContext()), 0, 0);
    }

    private void setupModelObserver() {
        // vCard
        mVCardViewModel = ViewModelProviders.of(this).get(VCardSyncViewModel.class);

        final Observer<BackupFileRestoreResponse> vCardRestoreResponseObserver =
                new Observer<BackupFileRestoreResponse>() {
                    @Override
                    public void onChanged(@Nullable BackupFileRestoreResponse response) {
                        Log.i(TAG, "onChanged vCardRestoreResponse = " + response);
                        if (response != null) {
                            Log.d(TAG, "onChanged code = " + response.getCode()
                                    + "; msg = " + response.getMsg());
                            if (BaseViewModel.SERVER_RESULT_SUCCESS == response.getCode()) {
                                List<BackupFileRestoreResponse.DataBean> dataBeanList = response.getData();
                                if (dataBeanList != null && dataBeanList.size() > 0) {
                                    long lastTimeStamp = -1;
                                    ArrayList<Integer> vCardIds = new ArrayList<>();
                                    SyncAssistantApplication.getsInstance().mAllVCards.clear();
                                    int listIndex = 0;
                                    for (BackupFileRestoreResponse.DataBean dataBean : dataBeanList) {
                                        if (lastTimeStamp < dataBean.getCreateAt()) {
                                            lastTimeStamp = dataBean.getCreateAt();
                                            SyncAssistantApplication.getsInstance().mVCardInfo
                                                    .setCount(dataBean.getCount());
                                            SyncAssistantApplication.getsInstance().mVCardInfo
                                                    .setId(dataBean.getId());
                                            SyncAssistantApplication.getsInstance().mVCardInfo
                                                    .setPath(dataBean.getPath());
                                            SyncAssistantApplication.getsInstance().mVCardInfo
                                                    .setHash(dataBean.getHash());
                                        }
                                        Log.d(TAG, "id = " + dataBean.getId()
                                                + "; createAt = " + dataBean.getCreateAt()
                                                + "; count = " + dataBean.getCount()
                                                + "; path = " + dataBean.getPath()
                                                + "; hash = " + dataBean.getHash());
                                        BackupFileInfo vCardInfo = new BackupFileInfo();
                                        vCardInfo.setId(dataBean.getId());
                                        vCardInfo.setPath(dataBean.getPath());
                                        vCardInfo.setHash(dataBean.getHash());
                                        vCardInfo.setCount(dataBean.getCount());
                                        vCardInfo.setCreateAt(dataBean.getCreateAt());
                                        if (listIndex < SyncAssistantApplication.MAX_BACKUP_FILE_ALLOWED) {
                                            SyncAssistantApplication.getsInstance().mAllVCards
                                                    .append(listIndex, vCardInfo);
                                        } else {
                                            vCardIds.add(dataBean.getId());
                                        }
                                        listIndex++;
                                    }
                                    if (SyncAssistantApplication.getsInstance().mVCardInfo.getPath()
                                            != null) {
                                        mContactsCountTV.setText(
                                                getString(R.string.item_count_on_server,
                                                SyncAssistantApplication.getsInstance()
                                                        .mVCardInfo.getCount()));
                                        SyncAssistantApplication.getsInstance().mVCardInfo
                                                .setCreateAt(lastTimeStamp);
                                        setupBackupTimeStamp();
                                        // just a protection to prevent deleting last record
                                        int index = vCardIds.indexOf(SyncAssistantApplication.
                                                getsInstance().mVCardInfo.getId());
                                        if (index >= 0) {
                                            vCardIds.remove(index);
                                        }
                                        deleteOldVCardOnServer(vCardIds);
                                    }
                                }
                                mQueryVCardInfoSuccess = true;
                            } else if (BaseViewModel.SERVER_RESULT_ERROR_INVALID_TOKEN
                                    == response.getCode()) {
                                Toast.makeText(getApplicationContext(),
                                        R.string.error_login_token_expired,
                                        Toast.LENGTH_SHORT).show();
                                SyncAssistantApplication.getsInstance().clearToken();
                            }
                        }
                        showProgress(false);
                        if (mQueryVCardInfoSuccess && mRetryVCardQuery) {
                            Intent intent = new Intent(getApplicationContext(),
                                    ContactsSyncActivity.class);
                            startActivityForResult(intent, REQUEST_SYNC_CONTACTS);
                            mRetryVCardQuery = false;
                        }
                    }
                };
        mVCardViewModel.vcardRestoreResponse().observe(this, vCardRestoreResponseObserver);

        // SMS
        mSMSViewModel = ViewModelProviders.of(this).get(SMSSyncViewModel.class);

        final Observer<BackupFileRestoreResponse> smsRestoreResponseObserver =
                new Observer<BackupFileRestoreResponse>() {
                    @Override
                    public void onChanged(@Nullable BackupFileRestoreResponse response) {
                        Log.i(TAG, "onChanged smsRestoreResponse = " + response);
                        if (response != null) {
                            if (BaseViewModel.SERVER_RESULT_SUCCESS == response.getCode()) {
                                List<BackupFileRestoreResponse.DataBean> dataBeanList = response.getData();
                                if (dataBeanList != null && dataBeanList.size() > 0) {
                                    long lastTimeStamp = -1;
                                    ArrayList<Integer> smsIds = new ArrayList<>();
                                    SyncAssistantApplication.getsInstance().mAllSMSFiles.clear();
                                    int listIndex = 0;
                                    for (BackupFileRestoreResponse.DataBean dataBean : dataBeanList) {
                                        if (lastTimeStamp < dataBean.getCreateAt()) {
                                            lastTimeStamp = dataBean.getCreateAt();
                                            SyncAssistantApplication.getsInstance().mSMSInfo
                                                    .setCount(dataBean.getCount());
                                            SyncAssistantApplication.getsInstance().mSMSInfo
                                                    .setId(dataBean.getId());
                                            SyncAssistantApplication.getsInstance().mSMSInfo
                                                    .setPath(dataBean.getPath());
                                            SyncAssistantApplication.getsInstance().mSMSInfo
                                                    .setHash(dataBean.getHash());
                                        }
                                        Log.d(TAG, "id = " + dataBean.getId()
                                                + "; createAt = " + dataBean.getCreateAt()
                                                + "; count = " + dataBean.getCount()
                                                + "; path = " + dataBean.getPath()
                                                + "; hash = " + dataBean.getHash());
                                        BackupFileInfo smsInfo = new BackupFileInfo();
                                        smsInfo.setId(dataBean.getId());
                                        smsInfo.setPath(dataBean.getPath());
                                        smsInfo.setHash(dataBean.getHash());
                                        smsInfo.setCount(dataBean.getCount());
                                        smsInfo.setCreateAt(dataBean.getCreateAt());
                                        if (listIndex < SyncAssistantApplication.MAX_BACKUP_FILE_ALLOWED) {
                                            SyncAssistantApplication.getsInstance().mAllSMSFiles
                                                    .append(listIndex, smsInfo);
                                        } else {
                                            smsIds.add(dataBean.getId());
                                        }
                                        listIndex++;
                                    }
                                    if (SyncAssistantApplication.getsInstance().mSMSInfo.getPath()
                                            != null) {
                                        mSMSCountTV.setText(
                                                getString(R.string.item_count_on_server,
                                                        SyncAssistantApplication.getsInstance()
                                                                .mSMSInfo.getCount()));
                                        SyncAssistantApplication.getsInstance().mSMSInfo
                                                .setCreateAt(lastTimeStamp);
                                        setupBackupTimeStamp();
                                        // just a protection to prevent deleting last record
                                        int index = smsIds.indexOf(SyncAssistantApplication.
                                                getsInstance().mSMSInfo.getId());
                                        if (index >= 0) {
                                            smsIds.remove(index);
                                        }
                                        deleteOldSMSOnServer(smsIds);
                                    }
                                }
                                mQuerySMSInfoSuccess = true;
                            } else if (BaseViewModel.SERVER_RESULT_ERROR_INVALID_TOKEN
                                    == response.getCode()) {
                                Toast.makeText(getApplicationContext(),
                                        R.string.error_login_token_expired,
                                        Toast.LENGTH_SHORT).show();
                                SyncAssistantApplication.getsInstance().clearToken();
                            }
                        }
                        showProgress(false);
                        if (mQuerySMSInfoSuccess && mRetrySMSQuery) {
                            Intent intent = new Intent(getApplicationContext(),
                                    ContactsSyncActivity.class);
                            startActivityForResult(intent, REQUEST_SYNC_CONTACTS);
                            mRetrySMSQuery = false;
                        }
                    }
                };

        mSMSViewModel.smsRestoreResponse().observe(this, smsRestoreResponseObserver);
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        LocalBroadcastManager.getInstance(this).unregisterReceiver(mBroadcastReceiver);
    }

    @Override
    public void onClick(View v) {
            if (R.id.contacts_backup == v.getId()) {
            if (mQueryVCardInfoSuccess) {
                Intent intent = new Intent(this, ContactsSyncActivity.class);
                startActivityForResult(intent, REQUEST_SYNC_CONTACTS);
            } else { // query server info may failed, try again
                mRetryVCardQuery = true;
                queryServerVCardInfo();
            }
        } if (R.id.sms_backup == v.getId()) {
            if (mQuerySMSInfoSuccess) {
                Intent intent = new Intent(this, SMSSyncActivity.class);
                startActivityForResult(intent, REQUEST_SYNC_SMS);
            } else { // query server info may failed, try again
                mRetrySMSQuery = true;
                queryServerSMSInfo();
            }
        }else if(R.id.duoqin_logout_btn == v.getId()){
            if(SyncAssistantApplication.getsInstance().hasLogin()){
                if (Guard.isDuoqinGuardEnable(this)
                        && !VerifyGuardCodeHelper.isCodeVerified(this)) {
                    Intent intent = new Intent("com.duoqin.guard.verifyGuardCode");
                    intent.addCategory(Intent.CATEGORY_DEFAULT);
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    startActivityForResult(intent, REQUEST_VERIFY_GUARD_CODE);
                } else {
                    attemptLogout();
                }
            }else {
                Intent intent = new Intent(DuoqinAccount.INTENT_ACTION_LOGIN);
                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                intent.setPackage(getPackageName());
                startActivityForResult(intent, REQUEST_LOGIN);
            }

        }
        else {
            super.onClick(v);
        }
    }

    private void attemptLogout() {
        if (mAlertDialog == null) {
            AlertDialog.Builder builder = new AlertDialog.Builder(this)
                    .setMessage(R.string.action_sign_out_confirm)
                    .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            ViewModelProviders.of(SyncAssistantActivity.this)
                                    .get(LoginViewModel.class).logout(
                                    DuoqinAccount.getAccountToken(getApplicationContext()));
                            // NOTICE: No need to wait response
                            SyncAssistantApplication.getsInstance().clearUserInfo();
                            mAccountTV.setText(R.string.account_not_login);
                            mAccountTV.requestFocus();
                            //TODO
                            mQuerySMSInfoSuccess = false;
                            mQueryVCardInfoSuccess = false;
                            mLogOut.setText(SyncAssistantApplication.getsInstance().hasLogin()?getString(R.string.duoqin_log_out):getString(R.string.duoqin_register_login));
                        }
                    })
                    .setNegativeButton(android.R.string.cancel, null);
            mAlertDialog = builder.create();
        }
        mAlertDialog.show();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        Log.d(TAG, "onActivityResult resultCode = " + resultCode
                + "; requestCode = " + requestCode);
        if (RESULT_OK != resultCode) return;

        if (REQUEST_LOGIN == requestCode) {
            if (SyncAssistantApplication.getsInstance().hasLogin()) {
                mAccountTV.setText(DuoqinAccount.getAccountName(getApplicationContext()));
                mContactsBackUpView.requestFocus();
                queryServerVCardInfo();
                queryServerSMSInfo();
            }
        } else if (REQUEST_SYNC_CONTACTS == requestCode) {
            queryServerVCardInfo();
        } else if (REQUEST_SYNC_SMS == requestCode) {
            queryServerSMSInfo();
        } else if (REQUEST_VERIFY_GUARD_CODE == requestCode) {
            attemptLogout();
        }
    }

    private void setupBackupTimeStamp() {
        long currentTime = System.currentTimeMillis();
        int contactDate = (int) ((currentTime - SyncAssistantApplication.getsInstance()
                .mVCardInfo.getCreateAt()) / DateUtils.DAY_IN_MILLIS);
        int smsDate = (int) ((currentTime - SyncAssistantApplication.getsInstance()
                .mSMSInfo.getCreateAt()) / DateUtils.DAY_IN_MILLIS);
        if (contactDate < 0) {
            contactDate = 0;
        }
        if (smsDate < 0) {
            smsDate = 0;
        }
        mContactsBackUpTimeTV.setText(getString(R.string.date_from_last_backup, contactDate));
        mSmsBackUpTimeTV.setText(getString(R.string.date_from_last_backup, smsDate));
    }

    private void deleteOldVCardOnServer(ArrayList<Integer> vCardIds) {
        if (vCardIds != null && vCardIds.size() > 0) {
            for (int id : vCardIds) {
                Log.d(TAG, "delete old vcard id = " + id);
                mVCardViewModel.deleteVCard(DuoqinAccount.getAccountToken(getApplicationContext()),
                        String.valueOf(id));
            }
        }
    }

    private void deleteOldSMSOnServer(ArrayList<Integer> smsIds) {
        if (smsIds != null && smsIds.size() > 0) {
            for (int id : smsIds) {
                Log.d(TAG, "delete old sms id = " + id);
                mSMSViewModel.deleteSMS(DuoqinAccount.getAccountToken(getApplicationContext()),
                        String.valueOf(id));
            }
        }
    }

    /**
     * Shows the progress UI and hides the login form.
     */
    private void showProgress(final boolean show) {
        mContactsBackUpView.setEnabled(!show);
        mSmsBackupView.setEnabled(!show);

        int shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime);
        mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
        mProgressView.animate().setDuration(shortAnimTime).alpha(
                show ? 1 : 0).setListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
            }
        });
    }
}
